from popen2 import popen2
import os,time
class TremMessage:
	''' Messages
	Common Attributes:
	cmd, time

	Tremulous log attributes:
	slot, guid, name, oldname, ip, team, ping, weapon, textmsg, structure, stage
	'''
	def __init__(self):
		self.cmd=None
		self.time=None
		self.slot=None
		self.guid=None
		self.name=None
		self.oldname=None
		self.ip=None
		self.oldteam=None
		self.team=None
		self.ping=None
		self.weapon=None
		self.textmsg=None
		self.structure=None
		self.stage=None
	
class TremGame:
	''' representa una partida en tiempo real
		source(parser)
		
		
	'''
class TremListener:
	# player
	def ClientConnect(self, msg):
		''' args: msg.slot, msg.ip, msg.guid, msg.name '''
		pass
	def ClientDisconnect(self, msg):
		''' args: msg.ip, msg.guid, msg.name '''
		pass
	def ClientRename(self, msg):
		''' args: msg.ip, msg.guid, msg.name, msg.oldname '''
		pass	
	def ClientBegin(self, msg):
		''' args: msg.slot '''
		pass
	def ClientTeam(self, msg):
		''' args: msg.textmsg '''
		# name joined the humans
		# name left the aliens
		# name abandoned aliens and joined the humans
		pass
	def ClientTeamClass(self, msg):
		''' args: msg.slot, msg.team, msg.weapon '''
		# slot human ckit
		# slot alien level0
		pass
	def Decon(self, msg):
		''' args: msg.textmsg '''
		# 3 9 0: msg
		pass
	def Build(self, msg):
		''' args: msg.slot, msg.structure, msg.weapon, msg.textmsg '''
		# 3 9 0: msg
		pass
	def Kill(self, msg):
		''' args: msg.slot, msg.victim, msg.weapon, msg.textmsg '''
		# 1 2 4: msg
		pass
	def score(self, msg):
		# kills ping: 73 client: 1 name
		pass
	def say(self, msg):
		''' args: msg.name, msg.textmsg '''
		# info structure
		pass
	def sayteam(self, msg):
		''' args: msg.name, msg.textmsg '''
		# name: msg
		pass
	
	# Special events
	def Stage(self, msg):
		''' args: msg.team, msg.stage, msg.textmsg '''
		# A 2: alien reached Stage 2
		pass
	def Exit(self):
		''' args: msg.textmsg '''
		# Humans win.
		pass
	def ShutdownGame(self, msg):
		''' args: none '''
		# no arguments
		pass
	def InitGame(self, msg):
		''' args: none '''
		pass
	def RealTime(self, msg):
		''' args: msg.textmsg '''
		# YYYY/mm/dd hh:mm:ss
		pass
	def Admin_Command(self, msg):
		# name: command
		pass
	
class TremParser:
	def __init__(self):
		self.reset()
		self.resetListeners()
	def reset(self):
		#self.players=[(None,)*100]
		pass
	
	def __parse_slotipguidname(self, m):
		t=m.split(' ');
		slot=int(t[0])
		ip=t[1].strip('[]');
		guid=t[2].strip('()');
		name=' '.join(t[3:]).strip('"')
		return (slot, ip, guid, name)
	def __parse_clientteamclass(self, m):
		t=m.split(' ')
		return (int(t[0]),t[1],t[2])
			
	def __parse_slotipguidnameoldname(self, m):
		t=m.split(' ');
		slot=int(t[0])
		ip=t[1].strip('[]');
		guid=t[2].strip('()');
		t=(' '.join(t[3:])).split('->')
		#print (t)
		oldname=t[0].strip('"')
		name=t[1].strip('"')
		return (slot, ip, guid, name, oldname)
	
	def __parse_slotvictimweapontextmsg(self, m):
		t=m.split(':');
		t2=t[0].split(' ')
		return (int(t2[0]), int(t2[1]), int(t2[2]), ':'.join(t[1:]))
		
	def __parse_nametextmsg(self, m):
		t=m.split(':')
		name=t[0]
		textmsg=':'.join(t[:])
		return (name, textmsg)
	def __parse_nametextmsgclientteam(self, m):
		t=m.split(' ')
		name=' '.join(t[0:-3])
		if name.endswith("humans and"):
			name=' '.join(t[0:-6])
		elif name.endswith("aliens and"):
			name=' '.join(t[0:-7])
			
		textmsg=' '.join(t[-3:])
		return (name, textmsg)
		
	def parseLine(self, l):
		m=TremMessage()
		#print (l)
		rdate=l[:7]
		m.cmd=(l[7:].split(':')[0])
		rest=(':'.join(l[7:].split(':')[1:])).strip()
		if(m.cmd=='ClientConnect'):
			m.slot,m.ip,m.guid,m.name=self.__parse_slotipguidname(rest)
		elif(m.cmd=='ClientDisconnect'):
			m.slot,m.ip,m.guid,m.name=self.__parse_slotipguidname(rest)
		elif(m.cmd=='ClientBegin'):
			m.slot=rest
		elif(m.cmd=='ClientRename'):
			m.slot,m.ip,m.guid,m.name,m.oldname=self.__parse_slotipguidnameoldname(rest)
		elif(m.cmd=='ClientTeam'):
			m.name, m.textmsg=self.__parse_nametextmsgclientteam(rest)
		elif(m.cmd=='say'):
			m.name, m.textmsg=self.__parse_nametextmsg(rest)
		elif(m.cmd=='sayteam'):
			m.name, m.textmsg=self.__parse_nametextmsg(rest)
		elif(m.cmd=='Kill'):
			m.slot, m.victim, m.weapon, m.textmsg=self.__parse_slotvictimweapontextmsg(rest)
		elif(m.cmd=='Build' or m.cmd=='Decon'):
			m.slot, m.struct, m.weapon, m.textmsg=self.__parse_slotvictimweapontextmsg(rest)
		elif(m.cmd=='ClientTeamClass'):
			m.slot, m.team, m.weapon = self.__parse_clientteamclass(rest)
		#print(m.cmd)
		import string
		if m.name:
			m.name=string.strip(m.name, '" ')
		self.sendMessage(m)
		
			
	def resetListeners(self):
		self.listeners=[]
	
	def sendMessage(self, msg):
		for l in self.listeners:
			if hasattr(l, msg.cmd):
				c=getattr(l, msg.cmd)
				if(callable(c)):
					c(msg)
					
	def addListener(self, listener):
		self.listeners.append(listener)
		

class TremParserSocket(TremParser):
	def __init__(self):
		pass
		
class TremParserLogTail(TremParser):
	def __init__(self, logfile):
		self.logfile=logfile
		self.f=None
		self.is_running=False
		self.__openlog()
		TremParser.__init__(self)
		
	def __openlog(self, all=False):
		if self.f is None:
			self.f=file(self.logfile, 'r')
			self.logsize=os.stat(self.logfile)[6]
			if not all:
				self.f.seek(self.logsize)
		
	def __closelog(self):
		if self.f is not None:
			self.f.close()
			self.f=None
		
	def run(self):
		self.__openlog()
		self.is_running=True
		while(self.is_running):
			where=self.f.tell()
			self.logsize=os.stat(self.logfile)[6]

			#print ("where: %s logize: %s" % (where,self.logsize))

			l=self.f.readline()
			if not l:
				if where>self.logsize:
					# el archivo es movido y vuelto a crear por rotacion de log. volvemos a abrir
					self.__closelog()
					self.__openlog(True)
					#print("Abriendo y cerrando")
					continue

				time.sleep(1)
				self.f.seek(where)
			else:
				self.parseLine(l)
		
	def stop():
		self.is_running=False
		
	def sendMessage(self, msg):
		if msg.cmd=='Shutdown':
			self.__closelog()
			self.__openlog()
		TremParser.sendMessage(self, msg)

class TremParserLog(TremParser):
	def __init__(self, logfile):
		self.logfile=logfile
		self.f=None
		self.is_running=False
		self.__openlog()
		TremParser.__init__(self)
		
	def __openlog(self, all=False):
		if self.f is None:			
			self.f=file(self.logfile, 'r')
			
	def __closelog(self):
		if self.f is not None:
			self.f.close()
			self.f=None
		
	def run(self):
		self.__openlog()
		self.is_running=True
		while(self.is_running):			

			l=self.f.readline()
			if not l:
				self.is_running=False
			else:
				self.parseLine(l)
		
	def stop():
		self.is_running=False
		
	def sendMessage(self, msg):
		TremParser.sendMessage(self, msg)
